#include "stdafx.h"
#include "DummyReadingInformation.h"
#include <cmath>
#include "IReading.h"
#include "Reading.h"
#include "ITime.h"
#include "Time.h"
#include <list>
#include <set>
#include <memory>
#include <exception>
#include <string>


namespace Sensor {

	double DummyReadingInformation::getReadingValue(const int sensorId, const std::string readingType, const long int time) const {
		// Create SDBM hash of reading type
		unsigned long int readingTypeHash = 0;
		for (int i=0; i<readingType.size(); i++) {
			readingTypeHash += (unsigned long int) readingType[i] + (readingTypeHash << 6) + (readingTypeHash << 16) - readingTypeHash;
		}

		double value = 50;
		value += std::sin((time * 3.14 * 2) / (60 * 60 * 24) + std::sin((readingTypeHash * 3.14) / (60 * 60 * 24) + readingTypeHash / (60 * 60))) * 25;
		value += std::sin(sensorId / 60 + (sensorId + readingTypeHash) * 3.14) * 12.5;
		value += std::sin(time * 3.14) * 6.25;

		return value;
	}

	void DummyReadingInformation::update() {
	}

	std::list<std::unique_ptr<IReading>> DummyReadingInformation::getReading(const int sensorId, const std::string readingType, const ITime& start, const ITime& end) const {
		std::list<std::unique_ptr<IReading>> readings;

		std::set<std::string> readingTypes = getReadingTypes();
		if (readingTypes.find(readingType) != readingTypes.end()) { // Its one of the reading types that exists
			long int length = end.getDifferenceInSeconds(start);
		
			for (int i=0; i<length/readingInterval; i++) {
				long int readingTime = ((int) (start.getUnixTime() + i*readingInterval) / readingInterval) * readingInterval;

				std::unique_ptr<ITime> time( 
					new Time(readingTime)
					);

				readings.push_back(
					std::unique_ptr<IReading>(
						new Reading(
							sensorId,
							time,
							readingType,
							getReadingValue(sensorId, readingType, readingTime)
							)
						)
					);
			}
		}

		return readings;
	}

	std::set<std::string> DummyReadingInformation::getReadingTypes() const {
		std::set<std::string> readingTypes;
		readingTypes.insert("Temperature");
		readingTypes.insert("Moisture");
		readingTypes.insert("Voltage");
		return readingTypes;
	}

	std::set<int> DummyReadingInformation::getSensorIds(const ITime& start, const ITime& end) const {
		std::set<int> ids;
		ids.insert(38);
		ids.insert(42);
		ids.insert(97);
		return ids;
	}

	void DummyReadingInformation::onReading(std::unique_ptr<IReading>& reading) {

	}

}
